use mmu::address::VirtAddr;
// use mmu::memory::memory_get_mut;
// use mmu::memory::memory_get_ref;
use mmu::mm::*;
use mmu::mmu::*;
use mmu::page_manager::alloc_page;
use mmu::PAGE_SIZE;

#[test]
fn test_mm_insert() {
    let mut mm = MemoryManager::new();
    assert!(vaddr_to_paddr(mm.ppn(), 12.into()).is_none());
    assert!(vaddr_to_paddr(mm.ppn(), 4096.into()).is_none());
    mm.insert(1.into());
    assert!(vaddr_to_paddr(mm.ppn(), 4096.into()).is_some());
}

#[test]
fn test_more_vaddr_to_one_paddr() {
    let mut mm1 = MemoryManager::new();
    let mut mm2 = MemoryManager::new();

    let ppn = alloc_page();

    mm1.map(1.into(), ppn);
    mm2.map(2.into(), ppn);

    let paddr1 = vaddr_to_paddr(mm1.ppn(), VirtAddr::num_and_offset(1.into(), 32)).unwrap();
    let paddr2 = vaddr_to_paddr(mm2.ppn(), VirtAddr::num_and_offset(2.into(), 32)).unwrap();
    assert_eq!(paddr1, paddr2);
}

#[test]
fn test_multi_page_write_read() {
    let mut mm = MemoryManager::new();

    let bytes = include_bytes!("../content/mm.rs");
    assert_eq!(
        mm.write_bytes((5 * PAGE_SIZE + 1024).into(), bytes),
        0
    );

    for i in 0..30 {
        mm.insert((5 + i).into());
    }

    assert_eq!(
        mm.write_bytes((5 * PAGE_SIZE + 1024).into(), bytes),
        bytes.len()
    );

    for i in 0..30 {
        mm.unmap((5 + i).into());
    }

    assert_eq!(
        mm.write_bytes((5 * PAGE_SIZE + 1024).into(), bytes),
        0
    );

    for i in 0..10 {
        mm.insert((5 + i).into());
    }

    assert_eq!(
        mm.write_bytes((5 * PAGE_SIZE + 1024).into(), bytes),
        bytes.len()
    );

    let mut new_bytes = vec![0u8; bytes.len()];
    assert_eq!(
        mm.read_bytes((5 * PAGE_SIZE + 1024).into(), &mut new_bytes),
        new_bytes.len()
    );

    assert_eq!(new_bytes, bytes);
}